﻿using Microsoft.Owin;
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Common.JWT;
using System.IO;
using System.Configuration;
using System.Security.Claims;

namespace OAuthServerApi
{
    public class ServerApiMiddleware : OwinMiddleware
    {
        public IJsonToken jsonToken = new Common.JWT.JsonToken();
        public static readonly string signKey = ConfigurationManager.AppSettings["JwtSignKey"];

        public ServerApiMiddleware(OwinMiddleware next) : base(next)
        {
        }

        public override async Task Invoke(IOwinContext context)
        {
            context.Response.ContentType = "application/json;charset=utf8";
            if (context.Request.Method == "POST")
            {
                var list = await context.Request.ReadFormAsync();
                var action = list.Get("action");

                if (string.IsNullOrEmpty(action))
                {
                    await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 1002, msg = "不存在Action参数" }));
                    return;
                }
                var res = string.Empty;
                switch (action)
                {
                    case "client_register":
                        res = await SetClientRegister(list.Get("name"), list.Get("url"));
                        break;
                    case "user_login":
                        res = await GetLoginUser(list.Get("username"), list.Get("userpwd"), list.Get("client"));
                        context.Response.Cookies.Append(OwinCookieType.CookieUser, res, new CookieOptions()
                        {
                            HttpOnly = true,
                            Path = "/"
                        });
                        break;
                    case "user_grant":
                        var token = list.Get("token");
                        var tokenValue = jsonToken.Decode<string>(token, signKey);
                        if (string.IsNullOrEmpty(tokenValue))
                        {
                            await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 1005, msg = "令牌错误" }));
                            return;
                        }
                        var userCookieData = context.Request.Cookies[OwinCookieType.CookieUser];
                        var user = jsonToken.Decode<OAuthUser>(userCookieData, signKey);
                        var userIdentity = new OAuthUserIdentity() { IsGrantCode = false };
                        if (user != null)
                        {
                            userIdentity.IsGrantCode = true;
                            userIdentity.ClientHash = user.ClientHash;
                            userIdentity.UserHash = user.UserHash;
                        }
                        context.Response.Cookies.Delete(OwinCookieType.CookieUser);
                        if (ResponseType.code.ToString() == tokenValue)
                        {
                            context.Response.Cookies.Append(OwinCookieType.CookieUserIdentity, jsonToken.Encode(userIdentity, signKey), new CookieOptions()
                            {
                                HttpOnly = true,
                                Path = "/"
                            });
                        }
                        else if (ResponseType.token.ToString() == tokenValue)
                        {
                            context.Response.Cookies.Append(OwinCookieType.CookieImplicitUser, jsonToken.Encode(userIdentity, signKey), new CookieOptions()
                            {
                                HttpOnly = true,
                                Path = "/"
                            });
                        }
                        res = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(new { error = 0, data = new { grant = userIdentity.IsGrantCode, type = tokenValue } }));
                        break;
                }
                if (string.IsNullOrEmpty(res))
                {
                    await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 1004, msg = "数据获取错误" }));
                    return;
                }
                if (action == "user_login")
                {

                    await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 0, data = res }));
                }
                else
                {
                    await context.Response.WriteAsync(res);
                }

                #region 注释
                //using (var sr = new StreamReader(context.Request.Body))
                //{
                //    var body = await sr.ReadToEndAsync();
                //    var action = GetValue(body, "action");
                //    if (string.IsNullOrEmpty(action))
                //    {
                //        await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 1002, msg = "不存在Action参数" }));
                //        return;
                //    }
                //    var res = string.Empty;
                //    switch (action)
                //    {
                //        case "client_register":
                //            res = await SetClientRegister(GetValue(body, "name"), GetValue(body, "url"));
                //            break;
                //        case "user_login":
                //            res = await GetLoginUser(GetValue(body, "username"), GetValue(body, "userpwd"), GetValue(body, "client"));
                //            context.Response.Cookies.Append(OwinCookieType.CookieUser, res, new CookieOptions()
                //            {
                //                HttpOnly = true,
                //                Path = "/"
                //            });
                //            break;
                //        case "user_grant":
                //            var userCookieData = context.Request.Cookies[OwinCookieType.CookieUser];
                //            var user = jsonToken.Decode<OAuthUser>(userCookieData, signKey);
                //            var userIdentity = new OAuthUserIdentity() { IsGrantCode = false };
                //            if (user != null)
                //            {
                //                userIdentity.IsGrantCode = true;
                //                userIdentity.ClientHash = user.ClientHash;
                //                userIdentity.UserHash = user.UserHash;
                //            }
                //            context.Response.Cookies.Delete(OwinCookieType.CookieUser);
                //            context.Response.Cookies.Append(OwinCookieType.CookieUserIdentity, jsonToken.Encode(userIdentity, signKey), new CookieOptions()
                //            {
                //                HttpOnly = true,
                //                Path = "/"
                //            });
                //            res = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(new { error = 0, data = userIdentity.IsGrantCode }));
                //            break;
                //    }
                //    if (string.IsNullOrEmpty(res))
                //    {
                //        await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 1004, msg = "数据获取错误" }));
                //        return;
                //    }
                //    if (action == "user_login")
                //    {

                //        await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 0, data = res }));
                //    }
                //    else
                //    {
                //        await context.Response.WriteAsync(res);
                //    }
                //}
                #endregion

            }
            else
            {
                await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = 1001, msg = "不支持GET类型" }));
            }
        }

        #region API-Action
        /// <summary>
        /// 注册client
        /// </summary>
        /// <param name="name"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<string> SetClientRegister(string name, string url)
        {
            using (var db = new DbOAuthHelper())
            {
                var client = new OAuthClient()
                {
                    ClientHash = JwtHelper.MD5(string.Concat(Guid.NewGuid().ToString("n"), name)),
                    ClientName = name,
                    ClientRedirectUri = System.Web.HttpUtility.UrlDecode(url),
                    ClientSecret = JwtHelper.MD5(string.Concat(name, DateTime.Now.ToString("YYYYMMddHHmmss"), Guid.NewGuid().ToString("n")))
                };
                var num = await db.AddOAuthClient(client);
                if (num > 0)
                {
                    return JsonConvert.SerializeObject(new { error = 0, data = new { client_id = client.ClientHash, client_secret = client.ClientSecret } });
                }
                return JsonConvert.SerializeObject(new { error = 1003, msg = "注册失败" });
            }
        }
        /// <summary>
        /// 加密登录用户
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        public async Task<string> GetLoginUser(string name, string pass, string client_id)
        {
            using (var db = new DbOAuthHelper())
            {
                var user = await db.GetUser(name, JwtHelper.MD5(pass, 32));
                var signData = string.Empty;
                if (user != null)
                {
                    user.ClientHash = client_id;
                    signData = jsonToken.Encode(user, signKey);

                }
                return signData;
            }
        }
        #endregion

        #region API-Method
        /// <summary>
        /// 获取POST参数
        /// </summary>
        /// <param name="queryString"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetValue(string queryString, string key)
        {
            if (string.IsNullOrEmpty(queryString) || string.IsNullOrEmpty(key))
            {
                return null;
            }
            var arr = queryString.Split('&');
            foreach (var s in arr)
            {
                var arr2 = s.Split('=');
                if (arr2[0] == key)
                {
                    return arr2[1];
                }
            }
            return null;
        }

        #endregion
    }
}